#pragma once

#include <base.h>

#define EFI_ACPI_1_TABLE_GUID                        \
	{                                                  \
		0xeb9d2d30, 0x2d88, 0x11d3, {                    \
			0x9a, 0x16, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d \
		}                                                \
	}
#define EFI_ACPI_2_TABLE_GUID                        \
	{                                                  \
		0x8868e871, 0xe4f1, 0x11d3, {                    \
			0xbc, 0x22, 0x00, 0x80, 0xc7, 0x3c, 0x88, 0x81 \
		}                                                \
	}

#define ACPI_COMPARE_SIGNATURE(var, sig) ((var) == *(uint32_t *)(sig))

typedef struct __packed {
	uint32_t signature;
	uint32_t length;
	uint8_t revision;
	uint8_t checksum;
	uint8_t oem[6];
	uint8_t oem_tableID[8];
	uint32_t oem_version;
	uint32_t creator_id;
	uint32_t creator_revsion;
} acpi_table_header_t;

typedef struct __packed {
	uint8_t address_space_id;	 // 0 - system memory, 1 - system I/O
	uint8_t register_bit_width;
	uint8_t register_bit_offset;
	uint8_t reserved;
	uint64_t address;
} acpi_io_address_t;

typedef struct __packed {
	acpi_table_header_t header;
	uint32_t tables[0];
} acpi_rsdt_t;

typedef struct __packed {
	acpi_table_header_t header;
	uintptr_t tables[0];
} acpi_xsdt_t;

typedef struct __packed {
	char signature[8];
	uint8_t checksum;
	uint8_t oem_id[6];
	uint8_t revision;
	uint32_t rsdt_address;
	uint32_t length;
	acpi_xsdt_t *xsdt;
	uint8_t extended_checksum;
	uint8_t reserved[3];
} acpi_rsdp_t;

void acpi_init(void *rsdpv1, void *rsdpv2);
acpi_table_header_t *acpi_get_table(const char *signature);

// at mm/page_allocator.c
void acpi_free_reclaimable_memory();